package top.lunarye.modules.file.service.impl;

import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import top.lunarye.modules.file.entity.File;
import top.lunarye.modules.file.mapper.FileMapper;
import top.lunarye.modules.file.service.IFileService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import top.lunarye.modules.staff.entity.RoleEnum;
import top.lunarye.modules.staff.entity.Staff;
import top.lunarye.utils.RestResponse;
import top.lunarye.utils.SystemCode;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>
 * 文件表  服务实现类
 * </p>
 *
 * @author lunar
 * @since 2021-07-23
 */
@Service("FileServiceImpl")
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements IFileService {

    @Value("${file.max-file-size}")
    private String maxFileSize;

    @Value("${file.holder}")
    private String fileParentPath;

    private static final Long DEFAULT_SIZE = 10 * 1024 * 1024L;

    public RestResponse<Integer> uploadFile(MultipartFile multipartFile, String path, Staff staff) {
        if (null == multipartFile) {
            return RestResponse.fail(SystemCode.ParameterValidError.getCode(), "文件不能为空");
        }
        Long maxSize = DEFAULT_SIZE;
        if (StrUtil.isNotEmpty(maxFileSize)) {
            String maxSizeStr = maxFileSize.toLowerCase().replace("mb", "");
            maxSize = Integer.valueOf(maxSizeStr) * 1024 * 1024L;
        }
        if (multipartFile.getSize() > maxSize) {
            return RestResponse.fail(SystemCode.ParameterValidError.getCode(), "文件大小超过最大值");
        }
        String filePath = fileParentPath;
        if (StrUtil.isNotEmpty(path)) {
            filePath = filePath + "/" + path + "/";
        } else {
            filePath = filePath + "/file/";
        }
        java.io.File directory = new java.io.File(filePath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        String originFileName = multipartFile.getOriginalFilename();
        String newFileName = this.generateFileName(originFileName);
        java.io.File fileTemp = new java.io.File(new java.io.File(filePath + newFileName).getAbsolutePath());
        Integer fileId;
        try {
            multipartFile.transferTo(fileTemp);
            File insertFile = new File();
            insertFile.setUploadStaff(staff.getId());
            insertFile.setOriginName(originFileName);
            insertFile.setNewName(newFileName);
            insertFile.setFilePath(filePath + newFileName);
            boolean insertResult = this.save(insertFile);
            if (!insertResult) {
                if (fileTemp.exists() && fileTemp.isFile()) {
                    fileTemp.delete();
                }
                log.error("上传文件信息写入数据库时发生错误");
                return RestResponse.fail(SystemCode.InnerError.getCode(), "上传文件时发生错误");
            }
            fileId = insertFile.getId();
        } catch (IOException e) {
            if (fileTemp.exists() && fileTemp.isFile()) {
                fileTemp.delete();
            }
            log.error("", e);
            return RestResponse.fail(SystemCode.InnerError.getCode(), "上传文件时发生错误");
        }
        return RestResponse.ok(fileId);
    }

    public ResponseEntity<byte[]> downLoad(String fileName, HttpServletRequest request) {
        QueryWrapper<File> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(File::getNewName, fileName);
        File file = this.getOne(queryWrapper);
        if (null == file)
            throw new UtilException("文件不存在");
        return fileDownload(file.getFilePath(), file.getOriginName(), request);
    }

    public ResponseEntity<byte[]> downLoad(Integer id, HttpServletRequest request) {
        File file = getById(id);
        if (null == file)
            throw new UtilException("文件不存在");
        return fileDownload(file.getFilePath(), file.getOriginName(), request);
    }

    public ResponseEntity<byte[]> fileDownload(String key, String fileName, HttpServletRequest request) {
        java.io.File file = new java.io.File(key);
        return downloadMethod(file, fileName, request);
    }

    @Transactional(rollbackFor = {Exception.class, RuntimeException.class, UtilException.class})
    public RestResponse deleteById(Integer id, Staff staff) {
        File byId = getById(id);
        if (byId == null) {
            return RestResponse.fail(SystemCode.ParameterValidError.getCode(), "文件不存在");
        }
        if (staff.getRole().getId().equals(RoleEnum.student.getId()) && !byId.getUploadStaff().equals(staff.getId())) {
            return RestResponse.fail(SystemCode.AccessDenied.getCode(), "用户没有权限删除该文件");
        }

        boolean removeResult = removeById(id);
        if (removeResult) {
            String filePath = byId.getFilePath();
            java.io.File file = new java.io.File(filePath);
            boolean delete = file.delete();
            if (delete)
                return RestResponse.ok();
            else
                throw new UtilException("删除时发生错误");
        } else {
            return RestResponse.fail(SystemCode.InnerError.getCode(), "删除时发生错误");
        }


    }
}
